package com.dg.river.netty.auditdev;

import android.os.Handler;
import android.os.Message;
import android.util.Log;


import com.dg.river.core.MyApplication;
import com.dg.river.core.util.L;
import com.dg.river.core.util.SPUtils;
import com.dg.river.core.util.TextUtil;
import com.dg.river.core.util.VersionUtils;
import com.dg.river.netty.axle.msg2dev.BaseMsg;
import com.dg.river.netty.axle.msg2dev.DevMsg;
import com.dg.river.netty.axle.msg2dev.DevMsgHead;
import com.dg.river.netty.axle.msg2dev.MessageConst;
import com.dg.river.netty.axle.msg2dev.Msg01_AuditSignIn;
import com.dg.river.netty.axle.msg2dev.Msg05_Heartbeat;
import com.dg.river.netty.axledev.NotifyConst;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import static com.dg.river.netty.axle.msg2dev.MessageConst.MESSAGE_FLAG;
import static com.dg.river.netty.axle.msg2dev.MessageConst.MTYPE_HEARTBEAT;


public class AuditDevClient {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    private EventLoopGroup loopGroup;
    private Channel channel;
    private Bootstrap bootstrap;
    //服务器地址
    private InetSocketAddress SERVER_ADDRESS = new InetSocketAddress("192.168.1.37", 9090);

    //主窗口消息处理channel
    private Handler handler;
    //连接状态计数
    private final static int MIN_WAIT_SEC = 10;
    private final static int MAX_WAIT_SEC = 120;
    private final static int MAX_CONNECTFAIL_COUNT = 6;

    //重连等待时长
    private int connect_wait_sec;
    //重连次数
    private int connect_fail_count;

    //上次发送的报文id
    private short lastMsgId;
    //对应接收到的消息
    private DevMsg respMsg;

    /**
     *
     * @param aHandler
     */
    public AuditDevClient(Handler aHandler) {
        handler = aHandler;
        connect_fail_count = 0;
        connect_wait_sec = MIN_WAIT_SEC;
        lastMsgId = 0;
    }


    /**
     * 重置连接计数
     */
    private void resetConnectInfo(){
        connect_fail_count = 0;
        connect_wait_sec = MIN_WAIT_SEC;
    }

    /**
     * 增加重连计数
     */
    private void incConnectFail(){

        if (connect_fail_count < MAX_CONNECTFAIL_COUNT){
            connect_fail_count++;
            connect_wait_sec = MIN_WAIT_SEC;
        } else {
            connect_wait_sec = MAX_WAIT_SEC;
        }
    }

    public void start() {
        try {
            loopGroup = new NioEventLoopGroup();
            bootstrap = new Bootstrap();
            bootstrap.group(loopGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new AuditDevClientInitializer(this));
            doConnect();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 中断连接
     */
    public void doDisConnect(){
        if ((channel==null) || (!channel.isActive())) {
            //网络不通
            return ;
        }
        try {
            channel.close().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    /**
     * 连接服务器
     */
    protected void doConnect(){
        if ((channel!=null) && channel.isActive()){
            L.d("Hy",  "doConnect: channel 1");
            return;
        }
        L.d("Hy", "doConnect: channel 2");
        ChannelFuture future = bootstrap.connect(SERVER_ADDRESS);
        future.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (future.isSuccess()){
                    //连接成功，通知界面
                    channel = future.channel();
                    //通知界面
                    Message msg = new Message();
                    msg.what = NotifyConst.MT_NETSTAT;
                    msg.obj = SERVER_ADDRESS.toString()+"：连接成功";
                    notifyMsg(msg);
                    //复位等待次数
                    resetConnectInfo();
                    //TODO 发送签到指令
                    sendSigninMsg();
                } else {
                    logger.debug("连接失败", future.cause());
                    //连接失败， 增加等待次数
                    incConnectFail();
                    future.channel().close();
                    //重连
                    future.channel().eventLoop().schedule(new Runnable() {
                        @Override
                        public void run() {
                            doConnect();
                        }
                    }, connect_wait_sec, TimeUnit.SECONDS);
                }
            }
        });
    }

    public void sendPingMsg() {
        if ((channel!=null) && channel.isActive()) {
            Msg05_Heartbeat msgPing = new Msg05_Heartbeat();
            msgPing.setMsg("ping");
            sendDevMsg(msgPing, MTYPE_HEARTBEAT);
        }
    }

    /**
     * 签到注册指令
     */
    public void sendSigninMsg(){
        if ((channel!=null) && channel.isActive()) {
//            AxleDevInfo devInfo = MyApplication.getInstance().getAxleDevInfo();
//            Msg01_AuditSignIn msg01 = new Msg01_AuditSignIn();
//            msg01.setImei(devInfo.getImei());
//            msg01.setOperId("007");
//            msg01.setStationId(devInfo.getStationId());
//            msg01.setLaneIds(new String[]{"23"});
//            msg01.setSoftVer("2020060901");
//            msg01.setHardVer("2020060902");

            String  stationId  = (String) SPUtils.get(MyApplication.getAppContext(), "BIND_LANE", "stationId", "");
            String laneId = (String) SPUtils.get(MyApplication.getAppContext(), "BIND_LANE", "laneId", "");
            String deviceId = (String) SPUtils.get(MyApplication.getAppContext(), "BIND_LANE", "deviceId", "");
            String verName = VersionUtils.getVerName(MyApplication.getAppContext());
            String getSystemVersion = VersionUtils.GetSystemVersion();

            L.d("Hy", "sendSigninMsg: "+ stationId);
            L.d("Hy", "sendSigninMsg: "+ laneId);
            L.d("Hy", "sendSigninMsg: "+ verName);
            L.d("Hy",  "sendSigninMsg: "+ getSystemVersion);
            L.d("Hy", "sendSigninMsg: "+ deviceId);

            // 操作员的id暂时没有获取到
            Msg01_AuditSignIn msg01 = new Msg01_AuditSignIn();
            msg01.setImei("123465");
            msg01.setOperId("007");
            msg01.setStationId(stationId);
            msg01.setLaneIds(new String[]{laneId});
            msg01.setSoftVer(verName);
            msg01.setHardVer(getSystemVersion);
            sendDevMsg(msg01, MessageConst.MTYPE_AUDITSIGNIN);
        }
    }

    /**
     * 网络连接中断时
     */
    public void onDisconnect(){
        Message msg = new Message();
        msg.what = NotifyConst.MT_NETSTAT;
        msg.obj = SERVER_ADDRESS.toString()+"：断开连接，正在重连...";
        notifyMsg(msg);
        //断开后重连, 等几秒后
        loopGroup.schedule(new Runnable() {
            @Override
            public void run() {
                doConnect();
            }
        }, connect_wait_sec, TimeUnit.SECONDS);

    }

    public void notifyMsg(Message msg) {
        if (handler != null){
            handler.sendMessage(msg);
        }
    }

    public String getLocalIp(){
        if ((channel!=null) && channel.isActive()) {
            return ((InetSocketAddress)channel.localAddress()).getAddress().getHostAddress();
        } else {
            return "";
        }
    }

    /**
     * 发送消息
     * @param msg
     * @return
     */
    public boolean sendDevMsg(BaseMsg msg, short msgType) {
        if ((channel==null) || (!channel.isActive())) {
            //网络不通
            return false;
        }
        //填充报文
        DevMsg devMsg = new DevMsg();
        DevMsgHead head = new DevMsgHead();
        head.setMsgFlag((short) MESSAGE_FLAG);
        head.setVersion((short) 0x01);
        head.setMsgType(msgType);
        head.setDeviceId(50001);
        head.setMsgId(++lastMsgId);
        if (lastMsgId > 255){
            lastMsgId = 0;
        }
        head.setTimestamp(new Date());
        devMsg.setHeader(head);
        devMsg.setBody(msg);
        if ((channel!=null) && channel.isActive()) {
            channel.writeAndFlush(devMsg);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 接收到回应, 交于界面处理
     * @param in
     */
    public void onRecvMsg(DevMsg in) {
        logger.debug("收到消息....");
        //TODO 此处根据接收到的消息进行处理。Demo程序全都转到界面展示

        Message msg = new Message();
        msg.what = in.getHeader().getMsgType();
        msg.obj = in;
        notifyMsg(msg);
    }

    /**
     * 修改绑定信息 进行修改
     */
    public void modifyConnect(){
        if ((channel==null) || (!channel.isActive())) {
            //网络不通
            return ;
        }
        try {
            L.d("Hy", "modify: 断链" );
            channel.close().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        L.d("Hy", "modify: 修改" );

    }

}
